// ElasticsearchService.cs
using Elastic.Clients.Elasticsearch;
using Elastic.Clients.Elasticsearch.IndexManagement;
using Elastic.Transport;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;

namespace Beauty.Net.Elasticsearch
{
    /// <summary>
    /// Elasticsearch服务实现
    /// </summary>
    public class ElasticsearchService : IElasticsearchService, IDisposable
    {
        private readonly ElasticsearchClient _client;
        private readonly ILogger<ElasticsearchService> _logger;
        private readonly ElasticsearchConfig _config;
        private bool _disposed = false;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="client">Elasticsearch客户端（通过依赖注入）</param>
        /// <param name="config">配置选项</param>
        /// <param name="logger">日志记录器</param>
        public ElasticsearchService(ElasticsearchClient client, ElasticsearchConfig config, ILogger<ElasticsearchService> logger)
        {
            _client = client ?? throw new ArgumentNullException(nameof(client));
            _config = config ?? throw new ArgumentNullException(nameof(config));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            try
            {
                _logger.LogInformation("Elasticsearch client initialized successfully");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to initialize Elasticsearch client");
                throw;
            }
        }

        /// <summary>
        /// 索引单个文档
        /// </summary>
        public async Task<IndexResult> IndexAsync<T>(string indexName, T document, string? id = null) where T : class
        {
            try
            {
                var response = string.IsNullOrEmpty(id)
                    ? await _client.IndexAsync(document, idx => idx.Index(indexName))
                    : await _client.IndexAsync(document, idx => idx.Index(indexName).Id(id));

                return new IndexResult
                {
                    Id = response.Id,
                    IsSuccess = response.IsValidResponse,
                    Error = !response.IsValidResponse ? response.DebugInformation : null
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to index document to {IndexName}", indexName);
                return new IndexResult
                {
                    Id = id,
                    IsSuccess = false,
                    Error = ex.Message
                };
            }
        }

        /// <summary>
        /// 批量索引文档
        /// 说明：
        /// 原实现使用库内 `BulkOperation` / `BulkIndexOperation<T>` 导致类型无法解析。
        /// 这里改为逐条调用 `IndexAsync` 并汇总结果，避免对缺失类型的依赖。
        /// 若需性能优化，可改为使用客户端提供的批量流式 APIs（根据客户端版本）。
        /// </summary>
        public async Task<BulkResult> BulkIndexAsync<T>(string indexName, IEnumerable<T> documents) where T : class
        {
            if (string.IsNullOrEmpty(indexName))
                throw new ArgumentNullException(nameof(indexName));
            if (documents == null)
                throw new ArgumentNullException(nameof(documents));

            var docsList = documents.ToList();
            int successCount = 0;
            int failedCount = 0;
            var errors = new List<string>();

            foreach (var document in docsList)
            {
                try
                {
                    var response = await _client.IndexAsync(document, idx => idx.Index(indexName));
                    if (response.IsValidResponse)
                    {
                        successCount++;
                    }
                    else
                    {
                        failedCount++;
                        var err = response.DebugInformation ?? "Bulk index: invalid response";
                        errors.Add(err);
                        _logger.LogWarning("Bulk index item failed in {IndexName}: {Error}", indexName, err);
                    }
                }
                catch (Exception ex)
                {
                    failedCount++;
                    errors.Add(ex.Message);
                    _logger.LogError(ex, "Bulk index item exception in {IndexName}", indexName);
                }
            }

            return new BulkResult
            {
                SuccessCount = successCount,
                FailedCount = failedCount,
                IsSuccess = failedCount == 0,
                Errors = errors.Count > 0 ? errors : null
            };
        }

        /// <summary>
        /// 获取单个文档
        /// </summary>
        public async Task<T?> GetAsync<T>(string indexName, string id) where T : class
        {
            try
            {
                var response = await _client.GetAsync<T>(id, g => g.Index(indexName));
                return response.Source;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to get document {Id} from {IndexName}", id, indexName);
                return null;
            }
        }

        /// <summary>
        /// 更新文档
        /// </summary>
        public async Task<UpdateResult> UpdateAsync<T>(string indexName, string id, T document) where T : class
        {
            try
            {
                var response = await _client.UpdateAsync<T, T>(id, u => u.Index(indexName).Doc(document));

                return new UpdateResult
                {
                    Id = id,
                    IsSuccess = response.IsValidResponse,
                    Error = !response.IsValidResponse ? response.DebugInformation : null
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to update document {Id} in {IndexName}", id, indexName);
                return new UpdateResult
                {
                    Id = id,
                    IsSuccess = false,
                    Error = ex.Message
                };
            }
        }

        /// <summary>
        /// 删除文档
        /// </summary>
        public async Task<DeleteResult> DeleteAsync(string indexName, string id)
        {
            try
            {
                var response = await _client.DeleteAsync(id, d => d.Index(indexName));

                return new DeleteResult
                {
                    Id = id,
                    IsSuccess = response.IsValidResponse,
                    Error = !response.IsValidResponse ? response.DebugInformation : null
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to delete document {Id} from {IndexName}", id, indexName);
                return new DeleteResult
                {
                    Id = id,
                    IsSuccess = false,
                    Error = ex.Message
                };
            }
        }

        /// <summary>
        /// 搜索文档
        /// </summary>
        public async Task<SearchResult<T>> SearchAsync<T>(string indexName, object query, int from = 0, int size = 10) where T : class
        {
            try
            {
                // 将查询对象转换为JSON字符串
                var queryJson = JsonSerializer.Serialize(query);
                var response = await _client.SearchAsync<T>(s => s
                    .Index(indexName)
                    .From(from)
                    .Size(size)
                    .Query(q => q.QueryString(qs => qs.Query(queryJson))));

                return new SearchResult<T>
                {
                    Documents = response.Documents?.Where(doc => doc != null).ToList() ?? new List<T>(),
                    Total = response.Documents?.Count ?? 0,
                    Took = (int)response.Took,
                    IsSuccess = response.IsValidResponse,
                    Error = !response.IsValidResponse ? response.DebugInformation : null
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to search documents in {IndexName}", indexName);
                return new SearchResult<T>
                {
                    Documents = new List<T>(),
                    Total = 0,
                    Took = 0,
                    IsSuccess = false,
                    Error = ex.Message
                };
            }
        }

        /// <summary>
        /// 简单文本搜索
        /// </summary>
        public async Task<SearchResult<T>> SimpleSearchAsync<T>(string indexName, string field, string value, int from = 0, int size = 10) where T : class
        {
            // 参数验证
            if (string.IsNullOrEmpty(indexName))
                throw new ArgumentNullException(nameof(indexName));
            if (string.IsNullOrEmpty(field))
                throw new ArgumentNullException(nameof(field));
            if (string.IsNullOrEmpty(value))
                throw new ArgumentNullException(nameof(value));

            try
            {
                var response = await _client.SearchAsync<T>(s => s
                    .Index(indexName!)
                    .From(from)
                    .Size(size)
                    .Query(q => q.Match(m => m.Field(field!).Query(value!))));

                return new SearchResult<T>
                {
                    Documents = response.Documents?.Where(doc => doc != null).ToList() ?? new List<T>(), // 确保Documents始终非null且不含null元素
                    Total = response.Documents?.Count ?? 0,
                    Took = (int)response.Took,
                    IsSuccess = response.IsValidResponse,
                    Error = !response.IsValidResponse ? response.DebugInformation : null
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to simple search documents in {IndexName}", indexName);
                return new SearchResult<T>
                {
                    Documents = new List<T>(), // 使用空集合而不是null
                    Total = 0,
                    Took = 0,
                    IsSuccess = false,
                    Error = ex.Message
                };
            }
        }

        /// <summary>
        /// 创建索引
        /// </summary>
        public async Task<bool> CreateIndexAsync(string indexName, object? settings = null)
        {
            try
            {
                // 检查索引是否已存在
                var existsResponse = await _client.Indices.ExistsAsync(indexName);
                if (existsResponse.Exists)
                {
                    _logger.LogInformation("Index {IndexName} already exists", indexName);
                    return true;
                }

                // 创建索引请求
                var createRequest = new CreateIndexRequest(indexName);

                // 适配8.x API的索引设置
                createRequest.Settings = new Elastic.Clients.Elasticsearch.IndexManagement.IndexSettings
                {
                    NumberOfShards = _config.DefaultIndexSettings.NumberOfShards,
                    NumberOfReplicas = _config.DefaultIndexSettings.NumberOfReplicas
                };

                var response = await _client.Indices.CreateAsync(createRequest);

                // 添加别名
                if (response.IsValidResponse && _config.DefaultIndexSettings.Aliases.Count > 0)
                {
                    foreach (var alias in _config.DefaultIndexSettings.Aliases)
                    {
                        await _client.Indices.PutAliasAsync(new PutAliasRequest(indexName, alias));
                    }
                }

                return response.IsValidResponse;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to create index {IndexName}", indexName);
                return false;
            }
        }

        /// <summary>
        /// 删除索引
        /// </summary>
        public async Task<bool> DeleteIndexAsync(string indexName)
        {
            try
            {
                var response = await _client.Indices.DeleteAsync(indexName);
                return response.IsValidResponse;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to delete index {IndexName}", indexName);
                return false;
            }
        }

        /// <summary>
        /// 检查索引是否存在
        /// </summary>
        public async Task<bool> IndexExistsAsync(string indexName)
        {
            try
            {
                var response = await _client.Indices.ExistsAsync(indexName);
                return response.Exists;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to check if index {IndexName} exists", indexName);
                return false;
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    // 释放托管资源
                    // 释放托管资源 - ElasticsearchClient 不需要显式释放
                }
                _disposed = true;
            }
        }
    }
}